﻿using System;
using System.Configuration;
using System.ServiceProcess;
using System.IO;
using System.Collections.Generic;
using Microsoft.Win32;
using System.Windows.Forms;


namespace VOEISHubPushServiceClient
{
    class ServiceConfigurationManager
    {
        private string _ApplicationConfigPath;
        
        public string ApplicationConfigPath
        {
             get
             {
                 return _ApplicationConfigPath;
             }
            set
            {
                _ApplicationConfigPath = value;
            }
        }
        
        public ServiceConfigurationManager()
        {
            SetServiceConfigPath();
           _ApplicationConfigPath = Properties.Settings.Default.VOEISHubPushServicePath.ToString();
        }

        private void SetServiceConfigPath()
        {
            try
            {
                string strPath = "";
                RegistryKey services = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Services");
                if (services != null)
                {
                    strPath = "";
                    strPath = services.OpenSubKey("VOEIS Hub Push Service").GetValue("ImagePath").ToString();
                    strPath = strPath.Replace("\"", "");
                    strPath = strPath.Replace(".exe", ".exe.config");
                    Properties.Settings.Default.VOEISHubPushServicePath = strPath;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("VOEIS Hub Push Service Not Found", "Service Missing - application will now close.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                MessageBox.Show(ex.Message.ToString(), "Error");
                System.Environment.Exit(99);
            }
        }

        //TODO:  I should probably think about just pulling the file once and dumping the entries into a dictionary that can be obtained from a single point
        //  Possibly something like below, but pulling individual sections (i.e. ServiceDatabase, etc.) and returning the dictionary.
        public String ReadApplicationSetting(String settingName, String configPath)
        {
            String settingValue = "";
            
            try
            {                
                //I found that opening a config file that does not reside with it's host application with the OpenExeConfiguration() method will result in not being able to find
                //sections.  I am replacing this will a mapped configuration so I can load/unload/save config files to user's local drive as well as in the application folder.
                //Configuration config = ConfigurationManager.OpenExeConfiguration(configPath);
                //ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = configPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");

                settingValue = section.Settings.Get(settingName).Value.ValueXml.InnerXml.ToString();                
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error loading configuration", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
            return settingValue;
        }

        public Dictionary<string, string> ReadDatabaseSettings()
        {
            Dictionary<string,string> DBDictionary = new Dictionary<string, string>();

            try
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = _ApplicationConfigPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");

                DBDictionary.Add("ServiceSQLServer", section.Settings.Get("ServiceSQLServer").Value.ValueXml.InnerXml.ToString());
                DBDictionary.Add("ServiceDatabase", section.Settings.Get("ServiceDatabase").Value.ValueXml.InnerXml.ToString());
                DBDictionary.Add("ServiceAuthentication", section.Settings.Get("ServiceAuthentication").Value.ValueXml.InnerXml.ToString());
                DBDictionary.Add("ServiceUserName", section.Settings.Get("ServiceUserName").Value.ValueXml.InnerXml.ToString());
                DBDictionary.Add("ServicePassword", section.Settings.Get("ServicePassword").Value.ValueXml.InnerXml.ToString());
                DBDictionary.Add("ServiceMaxRecords", section.Settings.Get("ServiceMaxRecords").Value.ValueXml.InnerXml.ToString());
                DBDictionary.Add("DBTimeout", section.Settings.Get("DBTimeout").Value.ValueXml.InnerXml.ToString());

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error loading configuration", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }

            return DBDictionary;
        }

        public Dictionary<string, string> ReadHubAPISettings()
        {
            Dictionary<string, string> APIDictionary = new Dictionary<string, string>();

            try
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = _ApplicationConfigPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");

                APIDictionary.Add("APIKey", section.Settings.Get("APIKey").Value.ValueXml.InnerXml.ToString());
                APIDictionary.Add("VOEISHubURL", section.Settings.Get("VOEISHubURL").Value.ValueXml.InnerXml.ToString());
                APIDictionary.Add("DataCheckInterval", section.Settings.Get("DataCheckInterval").Value.ValueXml.InnerXml.ToString());
                APIDictionary.Add("HubTimeout", section.Settings.Get("HubTimeout").Value.ValueXml.InnerXml.ToString());
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error loading configuration", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }

            return APIDictionary;
        }

        public Dictionary<string, string> ReadNotificationSettings()
        {
            Dictionary<string, string> NotificationsDictionary = new Dictionary<string, string>();

            try
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = _ApplicationConfigPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");

                NotificationsDictionary.Add("MailEnabled", section.Settings.Get("MailEnabled").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailServer", section.Settings.Get("MailServer").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailPort", section.Settings.Get("MailPort").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("ServiceEmail", section.Settings.Get("ServiceEmail").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailSSL", section.Settings.Get("MailSSL").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailRecipients", section.Settings.Get("MailRecipients").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailAuthenticate", section.Settings.Get("MailAuthenticate").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailUserName", section.Settings.Get("MailUserName").Value.ValueXml.InnerXml.ToString());
                NotificationsDictionary.Add("MailPassword", section.Settings.Get("MailPassword").Value.ValueXml.InnerXml.ToString());
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error loading configuration", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }

            return NotificationsDictionary;
        }

        public void SaveApplicationSetting(String settingName, String settingValue, String configPath)
        {
            try
            {
                //Decrypt the file
                UnProtectSection(configPath, "applicationSettings");

                //Create references
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = configPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");

                //Get the target value
                dynamic origElement = section.Settings.Get(settingName);
                section.Settings.Remove(origElement);
                origElement.Value.ValueXml.InnerXml = settingValue;
                section.Settings.Add(origElement);

                //Save it
                config.Save(ConfigurationSaveMode.Full);

                //Encrypt it
                ProtectSection(configPath, "applicationSettings");

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error saving configuration", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
            
        }

        public void SaveSectionSettings(Dictionary<string, string> SectionSettings)
        {
            try
            {
                //Decrypt the file
                UnProtectSection(_ApplicationConfigPath, "applicationSettings");

                //Create references
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = _ApplicationConfigPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup("applicationSettings").Sections.Get("VOEISHubPushService.My.MySettings");

                //Update values
                foreach (KeyValuePair<string, string> kvp in SectionSettings)
                {
                    dynamic origElement = section.Settings.Get(kvp.Key.ToString());
                    section.Settings.Remove(origElement);
                    origElement.Value.ValueXml.InnerXml = kvp.Value.ToString();
                    section.Settings.Add(origElement);
                }

                //Save it
                config.Save(ConfigurationSaveMode.Full);

                //Encrypt it
                ProtectSection(_ApplicationConfigPath, "applicationSettings");
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error saving database configuration", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }
        
        public void SaveTemplate(string sourceConfigPath, string destConfigPath, Boolean encrypted)
        {
            try
            {
                //Decrypt and read the source file
                UnProtectSection(sourceConfigPath, "applicationSettings");

                //Get a variable to hold the file contents  
                string strFile = "";

                //Copy the file
                using (StreamReader sr = new StreamReader(sourceConfigPath))
                {
                    //Read the file
                    strFile = sr.ReadToEnd();
                }

                //Stream it to the new location
                using (StreamWriter sw = new StreamWriter(destConfigPath))
                {
                    sw.Write(strFile);
                }

                //Encrypt the template file if necessary
                if (encrypted)
                {
                    ProtectSection(destConfigPath, "applicationSettings");
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error saving configuration template.", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        public void LoadTemplate(Form1 frm1, string sourceConfigPath)
        {
            try
            {
                //Decrypt and read the source template
                Boolean isProtected = IsProtected(sourceConfigPath, "applicationSettings");
                if (isProtected)
                {
                    UnProtectSection(sourceConfigPath, "applicationSettings");
                }

                //Load each of the sections
                //frm1.PopulateConfiguration();
                frm1.LoadConfiguration(sourceConfigPath);

                //Encrypt if necessary
                if (isProtected)
                {
                    ProtectSection(sourceConfigPath, "applicationSettings");
                }

            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "Error loading configuration template.", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        public void ProtectSection(string configPath, string sectionName)
        {
            //Configuration config = ConfigurationManager.OpenExeConfiguration(System.IO.Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString());
            try
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = configPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup(sectionName).Sections.Get("VOEISHubPushService.My.MySettings");

                if (section != null &&
                          !section.SectionInformation.IsProtected)
                {
                    section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                    config.Save();
                }
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Error encrypting the service configuration file.", "Encryption Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        public void UnProtectSection(string configPath, string sectionName)
        {
            //Configuration config = ConfigurationManager.OpenExeConfiguration(System.IO.Path.GetFullPath(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).ToString());
            try
            {
                ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                fileMap.ExeConfigFilename = configPath;

                Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup(sectionName).Sections.Get("VOEISHubPushService.My.MySettings");

                if (section != null &&
                      section.SectionInformation.IsProtected)
                {
                    section.SectionInformation.UnprotectSection();
                    config.Save();
                }
            }
            catch
            {
                System.Windows.Forms.MessageBox.Show("Error protecting the service configuration file.", "Decryption Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }

        private Boolean IsProtected(string configPath, string sectionName)
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = configPath;

            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

            try
            {
                ClientSettingsSection section = (ClientSettingsSection)config.GetSectionGroup(sectionName).Sections.Get("VOEISHubPushService.My.MySettings");
                
                if (section != null && section.SectionInformation.IsProtected)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message.ToString(), "error");
                return false;
            }
        }
    }
}
